<script setup lang="ts">
import {ref, reactive, computed, onMounted} from 'vue'
import RankingList from "@/components/RankingList.vue";
import UserModal from "@/components/UserModal.vue";
import {updateScore} from '@/api'
import {formatterScore} from "@/utils/score";

const GRID_SIZE = ref(10)
const MINES_COUNT = ref(15)
const gameOver = ref(false)
const gameWon = ref(false)
const gameStarted = ref(false)
const startTime = ref(0)
const gameTime = ref(0)
const timerInterval = ref<NodeJS.Timeout | null>(null)

interface Cell {
  isMine: boolean
  revealed: boolean
  flagged: boolean
  neighborMines: number
}

const grid = reactive<Cell[][]>([])

const remainingMines = computed(() => {
  const flagsUsed = grid.flat().filter(cell => cell.flagged).length
  return MINES_COUNT.value - flagsUsed
})

const formattedTime = computed(() => {
  return formatterScore(gameTime.value)
})

onMounted(() => {
  initializeGrid()
})

function initializeGrid() {
  gameOver.value = false
  gameWon.value = false
  gameStarted.value = false
  startTime.value = 0
  gameTime.value = 0
  if (timerInterval.value) {
    clearInterval(timerInterval.value)
    timerInterval.value = null
  }

  // 创建空网格
  grid.splice(0, grid.length)
  for (let x = 0; x < GRID_SIZE.value; x++) {
    const row: Cell[] = []
    for (let y = 0; y < GRID_SIZE.value; y++) {
      row.push({
        isMine: false,
        revealed: false,
        flagged: false,
        neighborMines: 0
      })
    }
    grid.push(row)
  }
}

function startGame() {
  if (gameStarted.value) return

  gameStarted.value = true
  startTime.value = Date.now()
  timerInterval.value = setInterval(() => {
    gameTime.value = Math.floor((Date.now() - startTime.value) / 1000)
  }, 1000)

  // 放置地雷
  let minesPlaced = 0
  while (minesPlaced < MINES_COUNT.value) {
    const x = Math.floor(Math.random() * GRID_SIZE.value)
    const y = Math.floor(Math.random() * GRID_SIZE.value)
    if (!grid[x][y].isMine) {
      grid[x][y].isMine = true
      minesPlaced++
    }
  }

  // 计算相邻地雷数量
  for (let x = 0; x < GRID_SIZE.value; x++) {
    for (let y = 0; y < GRID_SIZE.value; y++) {
      if (!grid[x][y].isMine) {
        grid[x][y].neighborMines = countNeighborMines(x, y)
      }
    }
  }
}

function countNeighborMines(x: number, y: number): number {
  let count = 0
  for (let dx = -1; dx <= 1; dx++) {
    for (let dy = -1; dy <= 1; dy++) {
      const nx = x + dx
      const ny = y + dy
      if (nx >= 0 && nx < GRID_SIZE.value && ny >= 0 && ny < GRID_SIZE.value) {
        if (grid[nx][ny].isMine) count++
      }
    }
  }
  return count
}

function reveal(x: number, y: number) {
  if (gameOver.value || grid[x][y].flagged) return

  // 防止第一次点击不会踩到雷
  if (!gameStarted.value) {
    const firstClick = {x, y}
    startGame()

    // 如果第一次点击位置有地雷，重新生成游戏直到安全
    while (grid[firstClick.x][firstClick.y].isMine) {
      resetMines()
    }
  }

  if (grid[x][y].isMine) {
    gameOver.value = true
    if (timerInterval.value) clearInterval(timerInterval.value)
    revealAllMines()
    return
  }

  revealRecursive(x, y)
  checkWin()
}

function resetMines() {
  // 清除所有地雷
  for (let x = 0; x < GRID_SIZE.value; x++) {
    for (let y = 0; y < GRID_SIZE.value; y++) {
      grid[x][y].isMine = false
    }
  }

  // 放置地雷
  let minesPlaced = 0
  while (minesPlaced < MINES_COUNT.value) {
    const x = Math.floor(Math.random() * GRID_SIZE.value)
    const y = Math.floor(Math.random() * GRID_SIZE.value)
    if (!grid[x][y].isMine) {
      grid[x][y].isMine = true
      minesPlaced++
    }
  }

  // 重新计算所有格子的邻居地雷数
  for (let x = 0; x < GRID_SIZE.value; x++) {
    for (let y = 0; y < GRID_SIZE.value; y++) {
      if (!grid[x][y].isMine) {
        grid[x][y].neighborMines = countNeighborMines(x, y)
      }
    }
  }
}

function revealRecursive(x: number, y: number) {
  if (x < 0 || x >= GRID_SIZE.value || y < 0 || y >= GRID_SIZE.value) return
  if (grid[x][y].revealed || grid[x][y].flagged) return

  grid[x][y].revealed = true

  if (grid[x][y].neighborMines === 0) {
    for (let dx = -1; dx <= 1; dx++) {
      for (let dy = -1; dy <= 1; dy++) {
        if (dx !== 0 || dy !== 0) {
          revealRecursive(x + dx, y + dy)
        }
      }
    }
  }
}

function flag(x: number, y: number) {
  if (!gameStarted.value || gameOver.value || grid[x][y].revealed) return
  grid[x][y].flagged = !grid[x][y].flagged
  checkWin()
}

function revealAllMines() {
  for (let x = 0; x < GRID_SIZE.value; x++) {
    for (let y = 0; y < GRID_SIZE.value; y++) {
      if (grid[x][y].isMine) {
        grid[x][y].revealed = true
      }
    }
  }
}

function checkWin() {
  // 所有非地雷格子都被翻开
  let allSafeRevealed = true

  for (let x = 0; x < GRID_SIZE.value; x++) {
    for (let y = 0; y < GRID_SIZE.value; y++) {
      // 如果是安全格子且没有被翻开
      if (!grid[x][y].isMine && !grid[x][y].revealed) {
        allSafeRevealed = false
        break
      }
    }
    if (!allSafeRevealed) break
  }

  if (allSafeRevealed) {
    gameWon.value = true
    gameOver.value = true
    handleUpdateScore()
    if (timerInterval.value) clearInterval(timerInterval.value)
  }
}

function resetGame() {
  if (timerInterval.value) clearInterval(timerInterval.value)
  initializeGrid()
}

const RankingListRef = ref()

function viewRankingList() {
  RankingListRef.value.open()
}

const handleUpdateScore = async () => {
  try {
    await updateScore(gameTime.value)
  } finally {

  }
}

const UserModalRef = ref()
const viewUser = () => {
  UserModalRef.value.open()
}
</script>

<template>
  <RankingList ref="RankingListRef"/>
  <UserModal ref="UserModalRef"/>
  <div class="game-container">
    <div class="game-header">
      <div class="game-title">
        <span @click="viewUser">个人信息</span>
      </div>
      <a class="control-btn" @click.prevent="viewRankingList">
        <span>查看排行榜</span>
      </a>
      <div class="game-controls">
        <a class="control-link" href="https://gitee.com/antfl-game/minesweeper" title="源码" target="_blank">
          <img src="@/assets/icons/github.svg" alt="https://gitee.com/antfl-game/minesweeper">
        </a>
        <a class="control-link" href="https://qm.qq.com/q/KCSI9GMiE8" title="加入 Byteout 技术交流群" target="_blank">
          <img src="@/assets/icons/qr-code.svg" alt="https://qm.qq.com/q/KCSI9GMiE8">
        </a>
      </div>
    </div>

    <div class="game-stats">
      <div class="stat-box">
        <div class="stat-label">剩余地雷</div>
        <div class="stat-value">{{ remainingMines }}</div>
      </div>
      <div class="stat-box">
        <div class="stat-label">游戏时间</div>
        <div class="stat-value">{{ formattedTime }}</div>
      </div>
    </div>

    <div class="grid-container">
      <div class="grid">
        <div v-for="(row, x) in grid" :key="x" class="row">
          <div
              v-for="(cell, y) in row"
              :key="y"
              class="cell"
              :class="{
              'revealed': cell.revealed,
              'mine': cell.isMine && gameOver,
              'flagged': cell.flagged,
              [`num-${cell.neighborMines}`]: cell.revealed && !cell.isMine && cell.neighborMines > 0
            }"
              @click.left="reveal(x, y)"
              @click.right.prevent="flag(x, y)"
          >
            <template v-if="cell.revealed">
              {{ cell.isMine ? '💣' : cell.neighborMines > 0 ? cell.neighborMines : '' }}
            </template>
            <template v-else>
              {{ cell.flagged ? '🚩' : '' }}
            </template>
          </div>
        </div>
      </div>
    </div>

    <div class="game-actions">
      <button class="start-button" @click="startGame" v-if="!gameStarted">
        开始游戏
      </button>
      <button class="start-button" @click="resetGame" v-else>
        重新开始
      </button>
    </div>

    <div class="game-messages">
      <div v-if="gameWon" class="win-message">
        恭喜你赢了！🎉 用时: {{ formattedTime }}
      </div>
      <div v-if="gameOver && !gameWon" class="game-over-message">
        游戏结束！💥
      </div>
    </div>

    <div class="game-info">
      <div class="info-title">游戏说明</div>
      <div class="info-list">
        <div class="info-item">
          <div class="info-icon">
            🪲
          </div>
          <div class="info-text">左键点击：翻开格子</div>
        </div>
        <div class="info-item">
          <div class="info-icon">
            🍀
          </div>
          <div class="info-text">右键点击：放置 / 移除旗帜</div>
        </div>
        <div class="info-item">
          <div class="info-icon">
            🍏
          </div>
          <div class="info-text">数字表示周围 8 个格子中的地雷数量</div>
        </div>
        <div class="info-item">
          <div class="info-icon">
            🍃
          </div>
          <div class="info-text">翻开所有安全格子，无需标记所有地雷</div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.game-container {
  width: 100%;
  margin: 30px auto;
  max-width: 500px;
  background: white;
  border-radius: 5px;
  overflow: hidden;
}

.game-header {
  background: linear-gradient(to right, #0081ff, #0066cc);
  padding: 12px 20px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  color: white;
}

.game-title {
  font-size: 16px;
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
}

.game-controls {
  display: flex;
  align-items: center;
  gap: 15px;
}

.control-btn {
  display: flex;
  align-items: center;
  cursor: pointer;

  img {
    width: 20px;
    height: 20px;
  }
}

.control-link {
  background-color: rgba(255, 255, 255, 0.1);
  border-radius: 50%;
  width: 30px;
  height: 30px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
  font-size: 18px;
  cursor: pointer;
  transition: all 0.2s;

  img {
    width: 15px;
    height: 15px;
  }
}

.control-link:hover {
  background-color: rgba(255, 255, 255, 0.3);
  transform: scale(1.05);
}

.game-stats {
  padding: 12px 20px;
  display: flex;
  justify-content: space-between;
  background-color: #fff;
}

.stat-box {
  min-width: 100px;
  text-align: center;
}

.stat-label {
  font-size: 12px;
  color: #657786;
}

.stat-value {
  font-size: 16px;
  font-weight: 700;
  color: #0081ff;
}

.grid-container {
  text-align: center;
}

.grid {
  padding: 10px;
  background-color: #d1dde8;
  border-radius: 5px;
  display: inline-block;
  box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.1);
}

.row {
  display: flex;
}

.cell {
  width: 36px;
  height: 36px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-weight: 700;
  font-size: 18px;
  cursor: pointer;
  user-select: none;
  background: #e8f0f8;
  border: 2px solid;
  border-color: #c0d0e0 #a0b0c0 #a0b0c0 #c0d0e0;
  margin: 2px;
  border-radius: 5px;
  transition: all 0.1s;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.cell:hover {
  background: #d8e8f8;
}

.cell.revealed {
  background: #d1dde8;
  border: 1px solid #a0b0c0;
}

.cell.mine {
  background: #ff4d4d;
}

.cell.flagged {
  color: #ff4d4d;
}

.game-actions {
  display: flex;
  justify-content: center;
  margin-top: 15px;
}

.start-button {
  background: linear-gradient(to right, #0081ff, #0066cc);
  color: white;
  border: none;
  border-radius: 5px;
  padding: 8px 40px;
  font-size: 16px;
  cursor: pointer;
  transition: all 0.3s;
  box-shadow: 0 4px 12px rgba(0, 129, 255, 0.3);
}

.start-button:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 15px rgba(0, 129, 255, 0.4);
}

.start-button:active {
  transform: translateY(0);
}

.game-messages {
  padding: 10px 0;
}

.win-message, .game-over-message {
  color: #00c853;
  text-align: center;
  font-size: 15px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}

.game-over-message {
  color: #ff5252;
}

.game-info {
  border-top: 1px solid #eee;
  padding: 10px 20px;
}

.info-title {
  font-size: 16px;
  color: #0081ff;
  margin: 6px 15px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.info-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 15px;
}

.info-item {
  padding: 12px;
  display: flex;
  gap: 10px;
}

.info-icon {
  width: 36px;
  height: 36px;
  background-color: #f9f9f9;
  border: 1px solid #eee;
  border-radius: 5px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #0081ff;
  flex-shrink: 0;
}

.info-text {
  font-size: 14px;
  color: #333;
}

@media (max-width: 480px) {
  .game-container {
    border-radius: 0;
    margin-top: 0;
  }

  .stat-box {
    min-width: 80px;
    padding: 8px 10px;
  }

  .stat-value {
    font-size: 20px;
  }

  .cell {
    width: 32px;
    height: 32px;
    font-size: 16px;
  }

  .info-list {
    grid-template-columns: 1fr;
  }
}
</style>